Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/component/PermissionsSection.kt renovate/fastlane-2.x-lockfile (056eed64) Text, 15.05 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.settings.component

Tff7b72import T7ee787androidx.compose.foundation.layout.ColumnScope
Tff7b72import T7ee787androidx.compose.material3.MaterialTheme
Tff7b72import T7ee787androidx.compose.runtime.Composable
Tff7b72import T7ee787androidx.compose.runtime.getValue
Tff7b72import T7ee787androidx.compose.runtime.mutableStateOf
Tff7b72import T7ee787androidx.compose.runtime.remember
Tff7b72import T7ee787androidx.compose.runtime.setValue
Tff7b72import T7ee787androidx.compose.ui.graphics.Color
Tff7b72import T7ee787androidx.compose.ui.graphics.vector.ImageVector
Tff7b72import T7ee787org.jetbrains.compose.resources.StringResource
Tff7b72import T7ee787org.jetbrains.compose.resources.pluralStringResource
Tff7b72import T7ee787org.jetbrains.compose.resources.stringResource
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.app_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.bluetooth_permission_rationale
Tff7b72import T7ee787org.meshtastic.core.resources.bluetooth_permission_rationale_pre31
Tff7b72import T7ee787org.meshtastic.core.resources.camera_permission
Tff7b72import T7ee787org.meshtastic.core.resources.camera_permission_rationale
Tff7b72import T7ee787org.meshtastic.core.resources.local_network_permission
Tff7b72import T7ee787org.meshtastic.core.resources.local_network_permission_rationale
Tff7b72import T7ee787org.meshtastic.core.resources.location_permission
Tff7b72import T7ee787org.meshtastic.core.resources.location_permission_rationale
Tff7b72import T7ee787org.meshtastic.core.resources.nearby_devices_permission
Tff7b72import T7ee787org.meshtastic.core.resources.notification_permission_rationale
Tff7b72import T7ee787org.meshtastic.core.resources.permission_camera_summary
Tff7b72import T7ee787org.meshtastic.core.resources.permission_local_network_summary
Tff7b72import T7ee787org.meshtastic.core.resources.permission_location_summary
Tff7b72import T7ee787org.meshtastic.core.resources.permission_location_summary_pre31
Tff7b72import T7ee787org.meshtastic.core.resources.permission_nearby_devices_summary
Tff7b72import T7ee787org.meshtastic.core.resources.permission_notifications_summary
Tff7b72import T7ee787org.meshtastic.core.resources.permission_state_allowed
Tff7b72import T7ee787org.meshtastic.core.resources.permission_state_blocked
Tff7b72import T7ee787org.meshtastic.core.resources.permission_state_denied
Tff7b72import T7ee787org.meshtastic.core.resources.permission_state_not_applicable
Tff7b72import T7ee787org.meshtastic.core.resources.permission_state_not_asked
Tff7b72import T7ee787org.meshtastic.core.resources.permissions
Tff7b72import T7ee787org.meshtastic.core.resources.permissions_all_allowed
Tff7b72import T7ee787org.meshtastic.core.resources.permissions_need_attention
Tff7b72import T7ee787org.meshtastic.core.resources.permissions_nothing_needed
Tff7b72import T7ee787org.meshtastic.core.ui.component.ListItem
Tff7b72import T7ee787org.meshtastic.core.ui.component.PermissionRationaleDialog
Tff7b72import T7ee787org.meshtastic.core.ui.icon.AppSettingsAlt
Tff7b72import T7ee787org.meshtastic.core.ui.icon.Bluetooth
Tff7b72import T7ee787org.meshtastic.core.ui.icon.ExpandLess
Tff7b72import T7ee787org.meshtastic.core.ui.icon.ExpandMore
Tff7b72import T7ee787org.meshtastic.core.ui.icon.Language
Tff7b72import T7ee787org.meshtastic.core.ui.icon.LocationOn
Tff7b72import T7ee787org.meshtastic.core.ui.icon.Lock
Tff7b72import T7ee787org.meshtastic.core.ui.icon.MeshtasticIcons
Tff7b72import T7ee787org.meshtastic.core.ui.icon.Notifications
Tff7b72import T7ee787org.meshtastic.core.ui.icon.QrCodeScanner
Tff7b72import T7ee787org.meshtastic.core.ui.util.PermissionGateAction
Tff7b72import T7ee787org.meshtastic.core.ui.util.PermissionStatus
Tff7b72import T7ee787org.meshtastic.core.ui.util.PermissionUiState
Tff7b72import T7ee787org.meshtastic.core.ui.util.bleScanRequiresLocationServices
Tff7b72import T7ee787org.meshtastic.core.ui.util.permissionGateAction
Tff7b72import T7ee787org.meshtastic.core.ui.util.rememberBluetoothPermissionState
Tff7b72import T7ee787org.meshtastic.core.ui.util.rememberCameraPermissionState
Tff7b72import T7ee787org.meshtastic.core.ui.util.rememberLocalNetworkPermissionState
Tff7b72import T7ee787org.meshtastic.core.ui.util.rememberLocationPermissionState
Tff7b72import T7ee787org.meshtastic.core.ui.util.rememberNotificationPermissionState

T8b949e/**
* One permission the app can ask for, as the permissions list needs to render it.
*
* @param titleRes The permission's name as the system presents it, so the row and the system screen agree.
* @param summaryRes What the app does with it, in the user's terms.
* @param rationaleRes The educational text shown before a re-request.
*/
Tff7b72private Tff7b72data Tff7b72class T56d364PermissionRowTb4b4b4(
Tff7b72val Te6edf3titleResTb4b4b4: Te6edf3StringResourceTb4b4b4,
Tff7b72val Te6edf3summaryResTb4b4b4: Te6edf3StringResourceTb4b4b4,
Tff7b72val Te6edf3rationaleResTb4b4b4: Te6edf3StringResourceTb4b4b4,
Tff7b72val Te6edf3iconTb4b4b4: Te6edf3ImageVectorTb4b4b4,
Tff7b72val Te6edf3stateTb4b4b4: Te6edf3PermissionUiStateTb4b4b4,
Tb4b4b4)

T8b949e/**
* A settings surface listing every runtime permission the app uses, its current state, and a way back to it.
*
* This exists because the onboarding flow runs exactly once. Before it, a user who skipped or denied a screen had no
* path back: the intro never returns, and the only recovery affordances lived inside the broken features themselves,
* reachable only by walking into one and guessing. POST_NOTIFICATIONS was the worst case — it had precisely one request
* site in the whole app, on a screen the user sees once, so declining it silently disabled every notification forever.
*
* Rows are actionable in the state the system allows: request while it will still prompt, an educational dialog first
* on a re-request, and the app's settings page once it will not prompt at all. A granted row still opens settings,
* because reviewing and revoking is as legitimate as granting.
*/
Tf0883e@Composable
Tff7b72internal Tff7b72fun Te6edf3ColumnScopeTb4b4b4.Td2a8ffPermissionsSettingsContentTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3bluetooth Tff7b72= Te6edf3rememberBluetoothPermissionStateTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3location Tff7b72= Te6edf3rememberLocationPermissionStateTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3notifications Tff7b72= Te6edf3rememberNotificationPermissionStateTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3camera Tff7b72= Te6edf3rememberCameraPermissionStateTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3localNetwork Tff7b72= Te6edf3rememberLocalNetworkPermissionStateTb4b4b4(Tb4b4b4)

T8b949e// Pre-Android-12 the BLE gate *is* ACCESS_FINE_LOCATION, so naming "Nearby devices" would point at a system screen
T8b949e// that does not exist on that device.
Tff7b72val Te6edf3bluetoothIsLocation Tff7b72= Te6edf3bleScanRequiresLocationServices

Tff7b72val Te6edf3rows Tff7b72=
Te6edf3permissionRowsTb4b4b4(
Te6edf3bluetooth Tff7b72= Te6edf3bluetoothTb4b4b4,
Te6edf3location Tff7b72= Te6edf3locationTb4b4b4,
Te6edf3notifications Tff7b72= Te6edf3notificationsTb4b4b4,
Te6edf3camera Tff7b72= Te6edf3cameraTb4b4b4,
Te6edf3localNetwork Tff7b72= Te6edf3localNetworkTb4b4b4,
Te6edf3bluetoothIsLocation Tff7b72= Te6edf3bluetoothIsLocationTb4b4b4,
Tb4b4b4)

T8b949e// Rows that need nothing from the user are collapsed by default. Five rows reading "Allowed" is a wall every
T8b949e// healthy user scrolls past on every visit to pay for a recovery path a minority needs — so the section leads with
T8b949e// the one fact that matters and opens itself only when something is actually wrong.
T8b949e//
T8b949e// "Needs attention" deliberately excludes NOT_REQUESTED. A permission the app has never asked for is not a
T8b949e// problem: a fresh install driven over USB legitimately holds none of these, and counting them would greet that
T8b949e// user with "5 need attention" about an app that is working perfectly.
Tff7b72val Te6edf3gatedRows Tff7b72= Te6edf3rowsTb4b4b4.Te6edf3filter Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3isRuntimeGated Tb4b4b4}
Tff7b72val Te6edf3needingAttention Tff7b72=
Te6edf3gatedRowsTb4b4b4.Te6edf3count Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3status Tff7b72=Tff7b72= Te6edf3PermissionStatusTb4b4b4.Te6edf3DENIED_CAN_RETRY Tff7b72|Tff7b72|
Tffa657itTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3status Tff7b72=Tff7b72= Te6edf3PermissionStatusTb4b4b4.Te6edf3PERMANENTLY_DENIED
Tb4b4b4}
Tff7b72val Te6edf3anyBlocked Tff7b72= Te6edf3gatedRowsTb4b4b4.Te6edf3any Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3status Tff7b72=Tff7b72= Te6edf3PermissionStatusTb4b4b4.Te6edf3PERMANENTLY_DENIED Tb4b4b4}
Tff7b72var Te6edf3expanded Tff7b72by Te6edf3rememberTb4b4b4(Te6edf3needingAttentionTb4b4b4) Tb4b4b4{ Te6edf3mutableStateOfTb4b4b4(Te6edf3needingAttention Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4}

Tff7b72var Te6edf3pendingRationale Tff7b72by Te6edf3remember Tb4b4b4{ Te6edf3mutableStateOfTff7b72<Te6edf3PermissionRow?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4) Tb4b4b4}

Te6edf3pendingRationaleTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3row Tff7b72-Tff7b72>
Te6edf3PermissionRationaleDialogTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3rowTb4b4b4.Te6edf3titleResTb4b4b4,
Te6edf3rationaleRes Tff7b72= Te6edf3rowTb4b4b4.Te6edf3rationaleResTb4b4b4,
Te6edf3icon Tff7b72= Te6edf3rowTb4b4b4.Te6edf3iconTb4b4b4,
Te6edf3onConfirm Tff7b72= Tb4b4b4{
Te6edf3pendingRationale Tff7b72= Tff7b72null
Te6edf3rowTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3requestTb4b4b4(Tb4b4b4)
Tb4b4b4}Tb4b4b4,
Te6edf3onDismiss Tff7b72= Tb4b4b4{ Te6edf3pendingRationale Tff7b72= Tff7b72null Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

Te6edf3ExpressiveSectionTb4b4b4(Te6edf3title Tff7b72= Te6edf3stringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permissionsTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ListItemTb4b4b4(
Te6edf3text Tff7b72= Te6edf3stringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permissionsTb4b4b4)Tb4b4b4,
Te6edf3supportingText Tff7b72=
Tff7b72when Tb4b4b4{
Te6edf3needingAttention Tff7b72> T79c0ff0 Tff7b72-Tff7b72>
Te6edf3pluralStringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3pluralsTb4b4b4.Te6edf3permissions_need_attentionTb4b4b4, Te6edf3needingAttentionTb4b4b4, Te6edf3needingAttentionTb4b4b4)

Te6edf3gatedRowsTb4b4b4.Te6edf3all Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3isGranted Tb4b4b4} Tff7b72-Tff7b72> Te6edf3stringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permissions_all_allowedTb4b4b4)

T8b949e// Some were never asked for. "All allowed" would be untrue, and anything alarming would be the
T8b949e// accusation this whole pass is about removing.
Tff7b72else Tff7b72-Tff7b72> Te6edf3stringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permissions_nothing_neededTb4b4b4)
Tb4b4b4}Tb4b4b4,
T8b949e// Same rule the individual rows follow: only a permanent denial is coloured, because only a permanent
T8b949e// denial actually leaves the user stuck. A retryable denial is a choice they are free to keep.
Te6edf3supportingTextColor Tff7b72= Tff7b72if Tb4b4b4(Te6edf3anyBlockedTb4b4b4) Te6edf3MaterialThemeTb4b4b4.Te6edf3colorSchemeTb4b4b4.Te6edf3error Tff7b72else Te6edf3ColorTb4b4b4.Te6edf3UnspecifiedTb4b4b4,
Te6edf3leadingIcon Tff7b72= Te6edf3MeshtasticIconsTb4b4b4.Te6edf3LockTb4b4b4,
Te6edf3trailingIcon Tff7b72= Tff7b72if Tb4b4b4(Te6edf3expandedTb4b4b4) Te6edf3MeshtasticIconsTb4b4b4.Te6edf3ExpandLess Tff7b72else Te6edf3MeshtasticIconsTb4b4b4.Te6edf3ExpandMoreTb4b4b4,
Te6edf3onClick Tff7b72= Tb4b4b4{ Te6edf3expanded Tff7b72= Tff7b72!Te6edf3expanded Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3expandedTb4b4b4) Tb4b4b4{
Te6edf3rowsTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3row Tff7b72-Tff7b72> Te6edf3PermissionListItemTb4b4b4(Te6edf3row Tff7b72= Te6edf3rowTb4b4b4, Te6edf3onShowRationale Tff7b72= Tb4b4b4{ Te6edf3pendingRationale Tff7b72= Te6edf3row Tb4b4b4}Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e/**
* The permission rows to show, in the order a user is most likely to need them.
*
* Split out of [PermissionsSettingsContent] so that composable stays about rendering and this stays about which
* permissions exist on the platform actually running.
*/
Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffpermissionRowsTb4b4b4(
Te6edf3bluetoothTb4b4b4: Te6edf3PermissionUiStateTb4b4b4,
Te6edf3locationTb4b4b4: Te6edf3PermissionUiStateTb4b4b4,
Te6edf3notificationsTb4b4b4: Te6edf3PermissionUiStateTb4b4b4,
Te6edf3cameraTb4b4b4: Te6edf3PermissionUiStateTb4b4b4,
Te6edf3localNetworkTb4b4b4: Te6edf3PermissionUiStateTb4b4b4,
Te6edf3bluetoothIsLocationTb4b4b4: Tffa657BooleanTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3ListTff7b72<Te6edf3PermissionRowTff7b72> Tff7b72= Te6edf3buildList Tb4b4b4{
T8b949e// Pre-Android-12 the Bluetooth gate *is* ACCESS_FINE_LOCATION. Two rows there would offer two controls for
T8b949e// one system grant and let them contradict each other on screen, so a single Location row stands for both.
Tff7b72if Tb4b4b4(Te6edf3bluetoothIsLocationTb4b4b4) Tb4b4b4{
Te6edf3addTb4b4b4(
Te6edf3PermissionRowTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3location_permissionTb4b4b4,
Te6edf3summaryRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_location_summary_pre31Tb4b4b4,
Te6edf3rationaleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3bluetooth_permission_rationale_pre31Tb4b4b4,
Te6edf3icon Tff7b72= Te6edf3MeshtasticIconsTb4b4b4.Te6edf3LocationOnTb4b4b4,
Te6edf3state Tff7b72= Te6edf3locationTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3addTb4b4b4(
Te6edf3PermissionRowTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3nearby_devices_permissionTb4b4b4,
Te6edf3summaryRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_nearby_devices_summaryTb4b4b4,
Te6edf3rationaleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3bluetooth_permission_rationaleTb4b4b4,
Te6edf3icon Tff7b72= Te6edf3MeshtasticIconsTb4b4b4.Te6edf3BluetoothTb4b4b4,
Te6edf3state Tff7b72= Te6edf3bluetoothTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3addTb4b4b4(
Te6edf3PermissionRowTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3location_permissionTb4b4b4,
Te6edf3summaryRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_location_summaryTb4b4b4,
Te6edf3rationaleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3location_permission_rationaleTb4b4b4,
Te6edf3icon Tff7b72= Te6edf3MeshtasticIconsTb4b4b4.Te6edf3LocationOnTb4b4b4,
Te6edf3state Tff7b72= Te6edf3locationTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3addTb4b4b4(
Te6edf3PermissionRowTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3app_notificationsTb4b4b4,
Te6edf3summaryRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_notifications_summaryTb4b4b4,
Te6edf3rationaleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3notification_permission_rationaleTb4b4b4,
Te6edf3icon Tff7b72= Te6edf3MeshtasticIconsTb4b4b4.Te6edf3NotificationsTb4b4b4,
Te6edf3state Tff7b72= Te6edf3notificationsTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3addTb4b4b4(
Te6edf3PermissionRowTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3camera_permissionTb4b4b4,
Te6edf3summaryRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_camera_summaryTb4b4b4,
Te6edf3rationaleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3camera_permission_rationaleTb4b4b4,
Te6edf3icon Tff7b72= Te6edf3MeshtasticIconsTb4b4b4.Te6edf3QrCodeScannerTb4b4b4,
Te6edf3state Tff7b72= Te6edf3cameraTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3addTb4b4b4(
Te6edf3PermissionRowTb4b4b4(
Te6edf3titleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_network_permissionTb4b4b4,
Te6edf3summaryRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_local_network_summaryTb4b4b4,
Te6edf3rationaleRes Tff7b72= Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_network_permission_rationaleTb4b4b4,
Te6edf3icon Tff7b72= Te6edf3MeshtasticIconsTb4b4b4.Te6edf3LanguageTb4b4b4,
Te6edf3state Tff7b72= Te6edf3localNetworkTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

T8b949e/** The one-line state a permissions row reports, kept out of the row composable's complexity budget. */
Tff7b72private Tff7b72fun Td2a8ffpermissionStateLabelTb4b4b4(Te6edf3statusTb4b4b4: Te6edf3PermissionStatusTb4b4b4, Te6edf3gatedTb4b4b4: Tffa657BooleanTb4b4b4)Tb4b4b4: Te6edf3StringResource Tff7b72= Tff7b72when Tb4b4b4{
Tff7b72!Te6edf3gated Tff7b72-Tff7b72> Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_state_not_applicable
Te6edf3status Tff7b72=Tff7b72= Te6edf3PermissionStatusTb4b4b4.Te6edf3GRANTED Tff7b72-Tff7b72> Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_state_allowed
Te6edf3status Tff7b72=Tff7b72= Te6edf3PermissionStatusTb4b4b4.Te6edf3NOT_REQUESTED Tff7b72-Tff7b72> Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_state_not_asked
Te6edf3status Tff7b72=Tff7b72= Te6edf3PermissionStatusTb4b4b4.Te6edf3DENIED_CAN_RETRY Tff7b72-Tff7b72> Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_state_denied
Tff7b72else Tff7b72-Tff7b72> Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3permission_state_blocked
Tb4b4b4}

Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffPermissionListItemTb4b4b4(Te6edf3rowTb4b4b4: Te6edf3PermissionRowTb4b4b4, Te6edf3onShowRationaleTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3state Tff7b72= Te6edf3rowTb4b4b4.Te6edf3state
Tff7b72val Te6edf3gated Tff7b72= Te6edf3stateTb4b4b4.Te6edf3isRuntimeGated

Tff7b72val Te6edf3statusRes Tff7b72= Te6edf3permissionStateLabelTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3statusTb4b4b4, Te6edf3gatedTb4b4b4)

T8b949e// Only a blocked permission is coloured. Denied is a choice the user made and is free to keep — colouring it red
T8b949e// would read as a scolding, which the permissions guidance explicitly warns against.
Tff7b72val Te6edf3statusColor Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3gated Tff7b72&Tff7b72& Te6edf3stateTb4b4b4.Te6edf3status Tff7b72=Tff7b72= Te6edf3PermissionStatusTb4b4b4.Te6edf3PERMANENTLY_DENIEDTb4b4b4) Tb4b4b4{
Te6edf3MaterialThemeTb4b4b4.Te6edf3colorSchemeTb4b4b4.Te6edf3error
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3ColorTb4b4b4.Te6edf3Unspecified
Tb4b4b4}

T8b949e// A chevron promises in-app navigation. Every action here that is not a request leaves for the system settings
T8b949e// app, so those rows say so instead.
Tff7b72val Te6edf3leavesTheApp Tff7b72=
Te6edf3gated Tff7b72&Tff7b72&
Te6edf3permissionGateActionTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3statusTb4b4b4) Tff7b72in
Te6edf3setOfTb4b4b4(Te6edf3PermissionGateActionTb4b4b4.Te6edf3PROCEEDTb4b4b4, Te6edf3PermissionGateActionTb4b4b4.Te6edf3OPEN_SETTINGSTb4b4b4)

Te6edf3ListItemTb4b4b4(
Te6edf3text Tff7b72= Te6edf3stringResourceTb4b4b4(Te6edf3rowTb4b4b4.Te6edf3titleResTb4b4b4)Tb4b4b4,
Te6edf3trailingIcon Tff7b72=
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3gatedTb4b4b4) Tb4b4b4{
Tff7b72null
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3leavesTheAppTb4b4b4) Tb4b4b4{
Te6edf3MeshtasticIconsTb4b4b4.Te6edf3AppSettingsAlt
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72null
Tb4b4b4}Tb4b4b4,
Te6edf3supportingText Tff7b72= Ta5d6ff"Tffd700${Te6edf3stringResourceTb4b4b4(Te6edf3rowTb4b4b4.Te6edf3summaryResTb4b4b4)Tffd700}Ta5d6ff\Ta5d6ffnTffd700${Te6edf3stringResourceTb4b4b4(Te6edf3statusResTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Te6edf3supportingTextColor Tff7b72= Te6edf3statusColorTb4b4b4,
Te6edf3leadingIcon Tff7b72= Te6edf3rowTb4b4b4.Te6edf3iconTb4b4b4,
Te6edf3enabled Tff7b72= Te6edf3gatedTb4b4b4,
Te6edf3onClick Tff7b72=
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3gatedTb4b4b4) Tb4b4b4{
Tff7b72null
Tb4b4b4} Tff7b72else Tb4b4b4{
Tb4b4b4{
Tff7b72when Tb4b4b4(Te6edf3permissionGateActionTb4b4b4(Te6edf3stateTb4b4b4.Te6edf3statusTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// Already held. Settings is still the useful destination — this is where a user comes to check
T8b949e// or
T8b949e// revoke, not only to grant.
Te6edf3PermissionGateActionTb4b4b4.Te6edf3PROCEED Tff7b72-Tff7b72> Te6edf3stateTb4b4b4.Te6edf3openAppSettingsTb4b4b4(Tb4b4b4)

Te6edf3PermissionGateActionTb4b4b4.Te6edf3REQUEST Tff7b72-Tff7b72> Te6edf3stateTb4b4b4.Te6edf3requestTb4b4b4(Tb4b4b4)

Te6edf3PermissionGateActionTb4b4b4.Te6edf3SHOW_RATIONALE Tff7b72-Tff7b72> Te6edf3onShowRationaleTb4b4b4(Tb4b4b4)

Te6edf3PermissionGateActionTb4b4b4.Te6edf3OPEN_SETTINGS Tff7b72-Tff7b72> Te6edf3stateTb4b4b4.Te6edf3openAppSettingsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

Served by rngit 1.5.4 - Generated in 0.09s